import { proxy, subscribe } from "valtio";
import { deepClone } from "valtio/utils";

// valtio proxy 返回类型
type ProxyState<T extends object> = ReturnType<typeof proxy<T>>;

export interface StoreOptions {
  /** 存储键名 */
  storageKey: string;
  /** 存储策略 */
  storageStrategy?: "localStorage" | "sessionStorage";
  /** 防抖延迟时间（毫秒），默认 300ms */
  debounceDelay?: number;
  /** 是否启用持久化，默认 true */
  enablePersistence?: boolean;
}

/**
 * 基于 valtio 的持久化存储代理类
 * 支持自动持久化到 localStorage 或 sessionStorage，并带有防抖处理
 */
export default class PersistentStore<T extends object> {
  /** 初始状态 */
  private initialState: T;
  /** 存储的值 */
  private _store: ProxyState<T>;
  /** 存储对象 */
  private storage: Storage = localStorage;
  /** 存储的键名 */
  private storageKey?: string;
  /** 防抖定时器 */
  private debounceTimer: NodeJS.Timeout | null = null;
  /** 防抖延迟时间 */
  private debounceDelay: number = 300;
  /** 是否启用持久化 */
  private enablePersistence?: boolean;

  constructor(initialState: T, options: StoreOptions) {
    this.initialState = deepClone(initialState);
    // 不存在指定存储key，则不进行持久化
    if (!options?.storageKey) {
      this._store = proxy<T>(deepClone(initialState));
      return;
    }
    // 配置持久化相关参数
    const { storageKey, storageStrategy = "localStorage", debounceDelay = 300, enablePersistence = true } = options;
    this.storageKey = storageKey;
    this.debounceDelay = debounceDelay;
    this.enablePersistence = enablePersistence;
    if (storageStrategy === "sessionStorage") {
      this.storage = sessionStorage;
    }
    // 尝试从存储中恢复数据 进行数据合并
    const persistedState = this.loadFromStorage();
    const initialStateToUse = persistedState ? { ...initialState, ...persistedState } : initialState;
    this._store = proxy<T>(deepClone(initialStateToUse as T));
    this.enablePersistence && this.setupPersistence();
  }
  get store() {
    return this._store;
  }

  /**
   * 从存储中加载数据
   */
  private loadFromStorage(): T | null {
    try {
      if (!this.storageKey) return null;
      const stored = this.storage.getItem(this.storageKey);
      if (!stored) return null;
      return JSON.parse(stored) as T;
    } catch (error) {
      console.warn(`[StoreProxy] 从 ${this.storage.constructor.name} 加载数据失败:`, error);
      return null;
    }
  }

  /**
   * 保存数据到存储（带防抖）
   */
  private saveToStorage(): void {
    if (!this.storageKey) return;
    const storageKey = this.storageKey; // 保存到局部变量以确保类型安全
    this.debounceTimer && clearTimeout(this.debounceTimer);
    // 设置新的防抖定时器
    this.debounceTimer = setTimeout(() => {
      try {
        const serialized = JSON.stringify(deepClone(this._store));
        this.storage.setItem(storageKey, serialized);
      } catch (error) {
        console.error(`[StoreProxy] 保存数据到 ${this.storage.constructor.name} 失败:`, error);
      } finally {
        this.debounceTimer = null;
      }
    }, this.debounceDelay);
  }

  /**
   * 设置持久化监听
   */
  private setupPersistence(): void {
    subscribe(this._store, () => {
      this.saveToStorage();
    });
  }
  /** 重置 store 为初始状态 */
  public resetStore(): void {
    this._store = proxy<T>(deepClone(this.initialState));
    this.enablePersistence && this.setupPersistence();
    this.saveToStorage();
  }
}
